package com.rockbb.common.utilities.internet;

import java.io.IOException;
import java.io.InputStream;
import java.util.zip.GZIPInputStream;

import javax.net.ssl.SSLHandshakeException;

import org.apache.http.Header;
import org.apache.http.HeaderElement;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.HttpResponseInterceptor;
import org.apache.http.HttpVersion;
import org.apache.http.NoHttpResponseException;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.params.CookiePolicy;
import org.apache.http.client.params.HttpClientParams;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.params.ConnManagerParams;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.HttpEntityWrapper;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.ExecutionContext;
import org.apache.http.protocol.HttpContext;

public class BaseClient {
	private DefaultHttpClient client;

	public BaseClient() {
		init();
	}

	public DefaultHttpClient getClient() {
		return client;
	}

	private void init() {
		// Create and initialize HTTP parameters  
		HttpParams params = new BasicHttpParams();  
		ConnManagerParams.setMaxTotalConnections(params, 100);  
		HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);

		// Specify IP address
		//params.setParameter(ConnRoutePNames.LOCAL_ADDRESS, "192.168.0.100");

		// Create and initialize scheme registry
		SchemeRegistry schemeRegistry = new SchemeRegistry();  
		schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));  
		schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));  

		// Create an HttpClient with the ThreadSafeClientConnManager.  
		// This connection manager must be used if more than one thread will  
		// be using the HttpClient.  
		ClientConnectionManager cm = new ThreadSafeClientConnManager(params, schemeRegistry);  

		client = new DefaultHttpClient(cm, params);
		HttpClientParams.setCookiePolicy(client.getParams(), CookiePolicy.BROWSER_COMPATIBILITY);

		HttpRequestRetryHandler myRetryHandler = new HttpRequestRetryHandler() {
		    public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
		        if (executionCount >= 5) {
		            // Do not retry if over max retry count
		            return false;
		        }
		        if (exception instanceof NoHttpResponseException) {
		            // Retry if the server dropped connection on us
		            return true;
		        }
		        if (exception instanceof SSLHandshakeException) {
		            // Do not retry on SSL handshake exception
		            return false;
		        }

		        HttpRequest request = (HttpRequest) context.getAttribute(ExecutionContext.HTTP_REQUEST);
		        boolean idempotent = !(request instanceof HttpEntityEnclosingRequest);
		        if (idempotent) {
		            // Retry if the request is considered idempotent
		            return true;
		        }
		        return false;
		    }
		};
		client.setHttpRequestRetryHandler(myRetryHandler);

		// Interceptor for gzip compressed content
        HttpResponseInterceptor myResInterceptor = new HttpResponseInterceptor() {  

            public void process(final HttpResponse response, final HttpContext context) {  
                HttpEntity entity = response.getEntity();  
                Header ceheader = entity.getContentEncoding();  
                if (ceheader != null) {  
                    HeaderElement[] codecs = ceheader.getElements();  
                    for (int i = 0; i < codecs.length; i++) {  
                        if (codecs[i].getName().equalsIgnoreCase("gzip")) {  
                            response.setEntity(new GzipDecompressingEntity(response.getEntity()));   
                            return;
                        }
                    }
                }
            }
        };
        client.addResponseInterceptor(myResInterceptor)	;
	}

	static class GzipDecompressingEntity extends HttpEntityWrapper {
        public GzipDecompressingEntity(final HttpEntity entity) {
            super(entity);
        }
        @Override
        public InputStream getContent()
            throws IOException, IllegalStateException {
            // the wrapped entity's getContent() decides about repeatability
            InputStream wrappedin = wrappedEntity.getContent();
            return new GZIPInputStream(wrappedin);
        }
        @Override
        public long getContentLength() {
            // length of ungzipped content is not known
            return -1;
        }
    }

}
